package cn.yl.fxboot.application.service;

import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;

import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.scheduling.annotation.Async;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import cn.yl.fxboot.application.action.MsgPaneActions;
import cn.yl.fxboot.application.common.utils.StringUtil;

@Async
public class DouyinHelper {
	
	/**
	 * 根据地址获取视频信息
	 * @param url
	 * @return
	 */
    public static Optional<DecodeVideo> decode(String url) {
        Document doc = Common.jsonpConnect(url, true);
        if(doc == null) {
        	return null;
        }
        // 获取作者信息
        Elements authorElements = doc.select("[class=\"user-info-name\"]");
        String author = "";
        if(authorElements.size() > 0) {
        	 author = StrUtil.removePrefix(authorElements.get(0).text(), "@");
        }
        // 获取头像
        Elements avatarElements = doc.select("[class=\"img-avator\"]");
        String avatar = avatarElements.attr("src").trim();
 
        // 构建基本信息
        DecodeVideo video = new DecodeVideo();
        video.setAuthor(author);
        video.setAvatar(avatar);
        // 获取itemInfo详细信息
        Elements scriptElements = doc.getElementsByTag("script");
        for (Element elements : scriptElements) {
            if (StrUtil.containsAny(elements.toString(), "douyin_falcon:page/reflow_video/index")) {
                String text = StrUtil.removeAllLineBreaks(StrUtil.removeAll(StrUtil.subBetween(elements.toString(), "({", "})"), '"')).trim();
                List<String> keys = StrUtil.splitTrim(text, ",");
                if (CollUtil.isNotEmpty(keys)) {
                    HashMap<String, String> params = MapUtil.newHashMap();
                    for (String key : keys) {
                        List<String> list = StrUtil.splitTrim(key, ":");
                        params.put(list.get(0), list.get(1));
                    }
                    String itemId = params.get("itemId");
                    String token = params.get("dytk");
                    String itemInfoUrl = StrFormatter.format("https://www.iesdouyin.com/web/api/v2/aweme/iteminfo/?item_ids={}&dytk={}", itemId, token);
                    String body = HttpUtil.get(itemInfoUrl);
                    if (StrUtil.isNotEmpty(body)) {
                        JSON json = JSONUtil.parse(body);
                        String statusCode = JSONUtil.getByPath(json, "status_code").toString();
                        if (StrUtil.equals(statusCode, "0")) {
                        	Object descObj = JSONUtil.getByPath(json, "item_list[0].desc");
                            String desc = descObj == null ? "" : descObj.toString();
                            Object addrObj = JSONUtil.getByPath(json, "item_list[0].video.play_addr.url_list[0]");
                            String addr = addrObj == null ? "" : addrObj.toString();
                            Object coverObj = JSONUtil.getByPath(json, "item_list[0].video.cover.url_list[0]");
                            String cover = coverObj == null ? "" : coverObj.toString();
                            //String playAddr = Common.getLocationUrl(addr);
                            Object playAddrObj = JSONUtil.getByPath(json, "item_list[0].video.play_addr.url_list[0]");
                            String playAddr = playAddrObj == null ? "" : playAddrObj.toString().replace("playwm", "play");
                            video.setAuthor(author);
                            video.setAvatar(avatar);
                            video.setCoverPicture(cover);
                            video.setTitle(desc);
                            video.setPlayAddr(playAddr);
                            break;
                        }
                    }
                }
            }
        }
        return Optional.ofNullable(video);
    }
    
    /**
     * 下载文件并保存相关信息
     * @param video
     * @param outPut
     * @return
     * @throws IOException
     */
    public static String download(DecodeVideo video,String outPut) throws IOException {
    	Map<String,String> headers = Common.getMobileHeaders();
    	//String playAddr = Common.getLocationUrl(video.getPlayAddr());
    	String playAddr = video.getPlayAddr();
    	HttpResponse resp = HttpUtil.createGet(playAddr).addHeaders(headers).execute();
    	byte[] bytes  = resp.bodyBytes();
    	byte[] extraBytes = UUID.fastUUID().toString().getBytes();
    	byte[] total = ArrayUtil.addAll(bytes,extraBytes);
    	File dir = new File(outPut + "\\" + video.getTitle()+System.currentTimeMillis());
    	if(!dir.exists()) {
    		dir.mkdirs();
    	}
    	File mp4 = new File(dir +"\\" + +System.currentTimeMillis() + ".mp4" );
    	mp4.createNewFile();
    	FileOutputStream fos = new FileOutputStream(mp4);
    	fos.write(total);
    	fos.close();
    	File txt = new File(dir +"\\" + +System.currentTimeMillis() + ".txt");
    	StringBuilder sb = new StringBuilder();
    	sb.append("标题  "+video.getTitle()).append(System.lineSeparator()).append(System.lineSeparator());
    	sb.append("作者  "+video.getAuthor()).append(System.lineSeparator()).append(System.lineSeparator());
    	sb.append("头像  "+video.getAvatar()).append(System.lineSeparator()).append(System.lineSeparator());
    	sb.append("封面  "+video.getCoverPicture()).append(System.lineSeparator()).append(System.lineSeparator());
    	sb.append("无水印视频地址  "+video.getPlayAddr()).append(System.lineSeparator()).append(System.lineSeparator());
    	FileWriter fw = new FileWriter(txt);
    	fw.write(sb.toString());
    	return dir.getPath();
    }
    
    /**
     * 仅下载文件
     * @param video
     * @param outPut
     * @return
     */
    public static String downloadOnlyVideoSingle(DecodeVideo video,String outPut)  {
    	try {
    		Map<String,String> headers = Common.getMobileHeaders();
    		//String playAddr = video.getPlayAddr();
    		String playAddr = Common.getLocationUrl(video.getPlayAddr());
        	HttpResponse resp = HttpUtil.createGet(playAddr).addHeaders(headers).execute();
        	byte[] bytes  = resp.bodyBytes();
        	File dir = new File(outPut);
        	if(!dir.exists()) {
        		dir.mkdirs();
        	}
        	String fileName = outPut +"\\"+System.currentTimeMillis() + StringUtil.removeTag(video.getTitle(), ".mp4") ;
        	File mp4 = new File(fileName);
        	mp4.createNewFile();
        	FileOutputStream fos = new FileOutputStream(mp4);
        	fos.write(bytes);
        	fos.close();
        	return fileName;
    	}catch (Exception e) {
    		MsgPaneActions.doLog("error:"+e.getMessage());
		}
    	return null;
    }
    
    /**
     * 仅下载文件
     * @param video
     * @param outPut
     * @return
     */
    public static String downloadOnlyVideo(DecodeVideo video,String outPut)  {
    	try {
    		Map<String,String> headers = Common.getMobileHeaders();
    		String playAddr = Common.getLocationUrl(video.getPlayAddr());
        	HttpResponse resp = HttpUtil.createGet(playAddr).addHeaders(headers).execute();
        	byte[] bytes  = resp.bodyBytes();
        	byte[] extraBytes = UUID.fastUUID().toString().getBytes();
        	byte[] total = ArrayUtil.addAll(bytes,extraBytes);
        	File dir = new File(outPut);
        	if(!dir.exists()) {
        		dir.mkdirs();
        	}
        	String fileName = outPut +"\\"+video.getAuthor() + "-"+video.getTitle() + ".mp4";//System.currentTimeMillis()  + StringUtil.removeTag(video.getTitle(), ".mp4") ;
        	File mp4 = new File(fileName);
        	mp4.createNewFile();
        	FileOutputStream fos = new FileOutputStream(mp4);
        	fos.write(total);
        	fos.close();
        	return fileName;
    	}catch (Exception e) {
    		MsgPaneActions.doLog("error:"+e.getMessage());
		}
    	return null;
    }
    
    /**
     * 把指定文件夹下的MP4文件按照文件名前缀合并
     * @param dir 文件夹
     * @param prefix 文件名前缀
     * @param outPut 输出文件路径
     * @return
     */
    public static String mixVideoByName(String dir,String outPut,String headFilePath,String endFilePath,String... prefixs) {
    	File file = new File(dir);
    	String[] fileNames = file.list();
    	if(fileNames != null && fileNames.length > 0) {
    		//创建一个以前缀为key，文件路径List为value的map，用以存储prefix
    		//迭代文件夹中的文件，并按照前缀分组
    		//TODO 由于存在嵌套循环，待优化
    		HashMap<String,ArrayList<String>> mergeMap = new HashMap<>();
    		for(String prefix : prefixs) {
    			ArrayList<String> tmp = new ArrayList<>();
    			for(String fileName : fileNames) {
    				if(StrUtil.startWith(fileName, prefix)) {
    					tmp.add(fileName);
    				}
    			}
    			mergeMap.put(prefix, tmp);
    		}
    		
    		//按prefix进行混合
    		for(Entry<String,ArrayList<String>> e : mergeMap.entrySet()) {
    			ArrayList<String> pathList = new ArrayList<>();
    			if(!StrUtil.isBlank(headFilePath)) {
    				pathList.add(headFilePath);
    			}
    			for(int i=0;i<e.getValue().size();i++) {
    				pathList.add(dir + "\\"+ e.getValue().get(i));
    			}
    			if(!StrUtil.isBlank(endFilePath)) {
    				pathList.add(endFilePath);
    			}
    			MixVideoUtil.javaMix(outPut, dir,pathList);
    			MsgPaneActions.doLog("success:混合"+e.getKey()+"完成");
    		}
    	}
    	return null;
    }
    
}
